#pragma once

namespace memento {
    
/// @brief 需求: 利用备忘录模式设计相亲游戏
///     假如有西施、王昭君、貂蝉、杨玉环四大美女同你相亲，你可以选择其中一位作为你的爱人，游戏提供后悔机制，不爱了可以换人

#include <iostream>
#include <string>
#include <vector>

/// @brief 备忘录, 提供了获取和存储美女信息的功能
class Memento_Girl {
public:
    Memento_Girl(const std::string& name) : name_(name) {}
    const std::string& GetName() const {
        return name_;
    }

private:
    std::string name_;
};

/// @brief 发起人, 记录当前时刻的内部状态信息（临时妻子的姓名）
class Originator_Man {
public:
    void SetGirlName(const std::string& girl) {
        girl_name_ = girl;
    }
    const std::string& GetGirlName() const {
        return girl_name_;
    }

    /// 提供创建备忘录和恢复备忘录数据的功能
    Memento_Girl* CreateMemento_Gril() {
        return new Memento_Girl(girl_name_);
    }
    void RestoreMemento(Memento_Girl* m) {
        SetGirlName(m->GetName());
    }

private:
    std::string girl_name_;
};

/// @brief 管理者, 对备忘录进行管理，用于保存相亲者（Man）前面选过的美女信息
class Caretaker_GirlStack {
public:
    ~Caretaker_GirlStack() {
        for (auto* girl : girls_) {
            delete girl;
        }
    }
    void Push(Memento_Girl* girl) {
        girls_.emplace_back(girl);
    }
    Memento_Girl* Pop() {
        Memento_Girl* girl = girls_.back();
        girls_.pop_back();
        return girl;
    }

private:
    std::vector<Memento_Girl*> girls_;
};

} // namespace memento

void Test_22_memento_impl_1() {
    printf("-------------------- %s --------------------\n", __FUNCTION__);
    std::shared_ptr<memento::Originator_Man> man_ptr(new memento::Originator_Man());
    std::shared_ptr<memento::Caretaker_GirlStack> girl_stack_ptr(new memento::Caretaker_GirlStack());

    man_ptr->SetGirlName("XiShi");
    girl_stack_ptr->Push(man_ptr->CreateMemento_Gril());
    printf("Now, You Select: %s\n", man_ptr->GetGirlName().c_str());
    
    man_ptr->SetGirlName("WangZhaoJun");
    printf("Now, You Reselect: %s\n", man_ptr->GetGirlName().c_str());

    man_ptr->RestoreMemento(girl_stack_ptr->Pop());
    printf("Now, You Restore To Select: %s\n", man_ptr->GetGirlName().c_str());
}

// -------------------- Test_22_memento_impl_1 --------------------
// Now, You Select: XiShi
// Now, You Reselect: WangZhaoJun
// Now, You Restore To Select: XiShi